home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 November / Macworld (1999-11).dmg / Updaters / WhiteCap 3.0.4 / WhiteCap Source.sit / WhiteCap Source / Common / Graphics / PixPort.cpp < prev    next >
C/C++ Source or Header  |  1999-08-28  |  37KB  |  1,593 lines

  1. #include "PixPort.h"
  2.  
  3. #include <math.h>
  4.  
  5. #if EG_MAC
  6. #include <QuickDraw.h>
  7. #include <QDOffscreen.h>
  8. #include <Displays.h>
  9. #include <string.h>
  10. #endif
  11.  
  12.  
  13. long        PixPort::sOSDepth            = 16;
  14. long        PixPort::sMinDepth             = 16;
  15. long        PixPort::sCanFullscreen        = false;
  16.  
  17.  
  18.     
  19.  
  20. void PixPort::Startup() {
  21.  
  22.     #if EG_MAC
  23.     #if USE_DRAW_SPROCKETS
  24.     OSStatus err = ::DSpStartup();
  25.     sCanFullscreen = err == 0;
  26.     #else
  27.     sCanFullscreen = false;
  28.     #endif
  29.     
  30.     GDHandle gDevice = ::GetMainDevice();
  31.     if ( gDevice )
  32.         sOSDepth = (**(**gDevice).gdPMap).pixelSize;
  33.     else
  34.         sOSDepth = 16;
  35.     #endif
  36.     
  37.     #if EG_WIN
  38.     
  39.     #if USE_DIRECTX
  40.     sCanFullscreen = true;
  41.     #else
  42.     sCanFullscreen = false;
  43.     #endif
  44.     HDC hdc = ::GetDC( NULL );
  45.     sOSDepth = ::GetDeviceCaps( hdc, BITSPIXEL );
  46.     ::ReleaseDC( NULL, hdc );
  47.     #endif
  48.     
  49. }
  50.  
  51.  
  52. void PixPort::Shutdown() {
  53.  
  54.     #if USE_DRAW_SPROCKETS
  55.     if ( sCanFullscreen )
  56.         ::DSpShutdown();
  57.     #endif
  58. }
  59.  
  60.  
  61.  
  62.  
  63. PixPort::PixPort() {
  64.     mBM = NULL;
  65.     mWorld = NULL;
  66.     mX = 0;
  67.     mY = 0;
  68.     mLineWidth = 1;
  69.     mBackColor    = 0;
  70.     mContextRef = 0;
  71.     mBytesPerPix = 0;
  72.  
  73.     #if EG_WIN
  74.     mWorld        = ::CreateCompatibleDC( NULL );
  75.     mBM            = NULL;
  76.     mDDObj        = NULL;
  77.     #endif
  78.     
  79.     #if EG_MAC
  80.     mHndlSize    = 0;
  81.     mTempHndl    = NULL;
  82.     #endif
  83. }
  84.  
  85.  
  86.  
  87. PixPort::~PixPort() {
  88.  
  89.     if ( IsFullscreen() )
  90.         Deactivate();
  91.  
  92.     #if EG_MAC
  93.     if ( mWorld ) {
  94.         ::UnlockPixels( mBM );
  95.         ::DisposeGWorld( mWorld );
  96.     }
  97.     
  98.     OSErr err;
  99.     if ( mTempHndl )
  100.         ::TempDisposeHandle( mTempHndl, &err );
  101.     #elif EG_WIN
  102.     if ( mWorld )
  103.         ::DeleteDC( mWorld );
  104.     if ( mBM )
  105.         ::DeleteObject( mBM );    
  106.     #endif
  107. }
  108.  
  109.  
  110.  
  111.  
  112.  
  113. long PixPort::GetOwningDisplay( const Point& inPt ) {
  114.     
  115.     #if EG_MAC
  116.     OSStatus            err;
  117.     DisplayIDType        id = 0;
  118.  
  119.  
  120.     GDHandle theGDevice;
  121.  
  122.     /*
  123.     ** Walk the list of display devices in the system.  DrawSprocket is
  124.     ** centered around the DisplayIDType, which is used by the Display
  125.     ** Manager.  The GDevice records are going to be in flux with future
  126.     ** versions of the system software, so it is best to make the change
  127.     ** now and make your software DisplayManager-centric.
  128.     */
  129.     theGDevice = DMGetFirstScreenDevice( false );
  130.     while( theGDevice && ! id ) {
  131.         
  132.         if ( ::PtInRect( inPt, &(**theGDevice).gdRect ) ) {
  133.         
  134.             /* get the display ID */
  135.             err = DMGetDisplayIDByGDevice( theGDevice, &id, false );
  136.             if ( err )
  137.                 id = 0;
  138.         }
  139.         
  140.         /* next device */
  141.         theGDevice = DMGetNextScreenDevice( theGDevice, false );
  142.     }    
  143. /*
  144.     err = ::DSpFindContextFromPoint( inPt, &ref );    
  145.     if ( ! err )
  146.         err = ::DSpContext_GetDisplayID( ref, &id );
  147. */
  148.     return ( err ) ? 0 : id;
  149.     #endif
  150.     
  151.     #if EG_WIN
  152.     #pragma unused ( inPt )
  153.     return 0;
  154.     #endif
  155. }
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169. void PixPort::UnionDirtyRect( const Rect* inDirtyRect ) {
  170.     
  171.     #if EG_MAC
  172.     #if USE_DRAW_SPROCKETS
  173.     if ( IsFullscreen() )
  174.         ::DSpContext_InvalBackBufferRect( mContextRef, inDirtyRect );    
  175.     #else
  176.     #pragma unused ( inDirtyRect )
  177.     #endif
  178.     #endif
  179.     
  180.     #if EG_WIN && USE_DIRECTX
  181.     if ( IsFullscreen() ) {
  182.         long w, h;
  183.         HDC hdc;
  184.         w = inDirtyRect -> right - inDirtyRect -> left;
  185.         h = inDirtyRect -> bottom - inDirtyRect -> top;
  186.         if ( mContextRef -> GetDC( &hdc ) == DD_OK ) {
  187.             ::BitBlt( hdc, inDirtyRect -> left, inDirtyRect -> top, w, h, mWorld, inDirtyRect -> left, inDirtyRect -> top, SRCCOPY );
  188.             mContextRef -> ReleaseDC( hdc );
  189.         }
  190.     }
  191.     #endif
  192. }
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200. bool PixPort::InitFullscreen( int inDispNum, Point& outSize, WindowPtr inWin, int inBitDepth ) {
  201.     bool ok = false;
  202.     
  203.     if ( inBitDepth != 8 || inBitDepth != 16 || inBitDepth != 32 )
  204.         inBitDepth = sOSDepth;
  205.         
  206.     // If we're already at fullscreen
  207.     if ( IsFullscreen() ) {
  208.         if ( mBytesPerPix * 8 == inBitDepth )
  209.             return true;
  210.         else
  211.             Deactivate();
  212.     }
  213.     
  214.     
  215.     #if EG_MAC
  216.     
  217.     #pragma unused( inWin )
  218.     
  219.     #if USE_DRAW_SPROCKETS
  220.     DSpContextReference        ref;
  221.     OSStatus                err;
  222.     DSpContextAttributes    context;
  223.     long                    bestWidth = 0x7FFFFFFF;
  224.     bool                     isInitted = false;
  225.  
  226.     if ( sCanFullscreen ) {
  227.         err = ::DSpGetFirstContext( inDispNum, &ref );
  228.         
  229.         // Look for smallest size w/ for given depth
  230.         while ( ! err ) {
  231.             err = DSpContext_GetAttributes( ref, &context );
  232.             if ( ! err ) {
  233.                 if ( context.displayWidth <= bestWidth && context.displayWidth >= 640 ) {
  234.                     if ( context.displayBestDepth == inBitDepth ) {
  235.                         mContextRef = ref;
  236.                         isInitted = true;
  237.                         bestWidth = context.displayWidth;
  238.                     }
  239.                 }
  240.             }
  241.             
  242.             // Try the next context for this display
  243.             err = ::DSpGetNextContext( ref, &ref );
  244.         }
  245.         
  246.         if ( ! isInitted ) {
  247.             mContextRef = 0;
  248.             return false;
  249.         }
  250.             
  251.         ::DSpContext_GetAttributes( mContextRef, &mContext );
  252.         outSize.h = mContext.displayWidth;
  253.         outSize.v = mContext.displayHeight;
  254.         
  255.         /*
  256.         ** Here is where I need to OR in the value to use page flipping.  If
  257.         ** I had used the value when calling DSpFindBestContext() then it would
  258.         ** have only considered displays that have page flipping hardware, but
  259.         ** I want to run with software buffering too.
  260.         */
  261.         mContext.contextOptions             = kDSpContextOption_PageFlip;
  262.         mContext.frequency                    = 0;
  263.         mContext.reserved1                    = 0;
  264.         mContext.reserved2                    = 0;
  265.         mContext.gameMustConfirmSwitch        = false;
  266.         mContext.reserved3[0]    = 0;
  267.         mContext.reserved3[1]    = 0;
  268.         mContext.reserved3[2]    = 0;
  269.         mContext.reserved3[3]    = 0;
  270.         mContext.colorTable        = 0;
  271.         mContext.pageCount        = 0;
  272.         mContext.colorNeeds        = kDSpColorNeeds_Require;
  273.                         
  274.         // Try to reserve the device
  275.         err = ::DSpContext_Reserve( mContextRef, &mContext );
  276.         if ( err ) {
  277.             mContextRef = 0;
  278.             return false;
  279.         }
  280.             
  281.         // If no errors, 'activate' the device into fullscreen
  282.         ::HideCursor();
  283.  
  284.         ::DSpContext_FadeGammaOut( mContextRef, NULL );
  285.  
  286.         err = ::DSpContext_SetState( mContextRef, kDSpContextState_Active );
  287.         
  288.         if ( err )
  289.             ::DSpContext_Release( mContextRef );
  290.         else {
  291.         
  292.             BeginFrame();
  293.             
  294.             // Load the key info about the fullscreen mode            
  295.             if ( mBM ) {
  296.             
  297.                 // If we have an offscreen world allocated, chuck it
  298.                 if ( mWorld ) {
  299.                     ::UnlockPixels( mBM );
  300.                     ::DisposeGWorld( mWorld );
  301.                     mWorld = NULL;
  302.                 }
  303.  
  304.                 mBytesPerRow    = (**mBM).rowBytes & 0xFFF;
  305.                 mBytesPerPix    = (**mBM).pixelSize / 8;
  306.                 mX                = (**mBM).bounds.right - (**mBM).bounds.left;
  307.                 mY                = (**mBM).bounds.bottom - (**mBM).bounds.top - 1;
  308.                 ok = true;
  309.             }
  310.         }
  311.         ::DSpContext_FadeGamma( mContextRef, 100, NULL );
  312.     }
  313.     #else
  314.     #pragma unused( inDispNum, outSize )
  315.     #endif
  316.     #endif
  317.     
  318.     #if EG_WIN
  319.     
  320.     #pragma unused( inDispNum )
  321.     
  322.     #if USE_DIRECTX
  323.     if ( sCanFullscreen ) {
  324.         HRESULT err = ::DirectDrawCreate( NULL, &mDDObj, NULL );
  325.         if ( err == DD_OK ) {
  326.             LPDIRECTDRAWSURFACE context;
  327.             
  328.             err = mDDObj -> SetCooperativeLevel( inWin, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
  329.             if ( err == DD_OK ) {
  330.                 err = mDDObj -> SetDisplayMode( 640, 480, inBitDepth );
  331.                 if ( err == DD_OK ) {
  332.                     DDSURFACEDESC ddsd;
  333.                     ddsd.dwSize = sizeof(ddsd);
  334.                     ddsd.dwFlags = DDSD_CAPS;
  335.                     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  336.                     err = mDDObj -> CreateSurface( &ddsd, &context, NULL);
  337.                 }
  338.             }
  339.             
  340.             if ( err == DD_OK ) {
  341.                 Init( 640, 480, inBitDepth );
  342.                 mContextRef = context;
  343.                 outSize.h = 640;
  344.                 outSize.v = 480;
  345.                 ::SetForegroundWindow( inWin );
  346.                 ::SetCapture( inWin );
  347.                 ::ShowCursor( false );
  348.                 ok = true; }
  349.             else {
  350.                  mDDObj -> Release();
  351.                  mDDObj = NULL;
  352.             }
  353.         }
  354.     }
  355.     #else
  356.     #pragma unused( outSize, inWin )
  357.     #endif
  358.     
  359.     #endif
  360.     
  361.     
  362.     if ( ! ok )
  363.         mContextRef = 0;
  364.         
  365.     return mContextRef;
  366. }
  367.  
  368.  
  369.  
  370.  
  371.  
  372. void PixPort::Init( int inWidth, int inHeight, int inDepth ) {
  373.         
  374.     if ( inWidth < 0 ) inWidth = 0;
  375.     if ( inHeight < 0 ) inHeight = 0;
  376.  
  377.     // Catch any invalid depth levels.
  378.     if ( inDepth != 32 && inDepth != 16 && inDepth != 8 )
  379.         inDepth = sOSDepth;
  380.     
  381.     // If we've been at full screen, take us out
  382.     if ( IsFullscreen() )
  383.         Deactivate();
  384.     else if ( mWorld && mBytesPerPix * 8 == inDepth && inWidth == mX && inHeight == mY )
  385.         return;
  386.     
  387.     mX            = 4 * (( inWidth + 3 ) / 4 );
  388.     mY            = inHeight;
  389.     
  390.         
  391.     #if EG_MAC
  392.     
  393.     // Save current draw envir
  394.     GDHandle        saveDev;
  395.      GrafPtr            savePort;
  396.     ::GetGWorld( (GWorldPtr*)(&savePort), &saveDev );
  397.     
  398.     if ( mWorld ) {
  399.         ::UnlockPixels( mBM );
  400.         ::DisposeGWorld( mWorld );
  401.     }
  402.     Rect r;
  403.     ::SetRect( &r, 0, 0, mX, mY+1 );
  404.     ::NewGWorld( &mWorld, inDepth, &r, NULL, NULL, useTempMem );
  405.     mBM = ::GetGWorldPixMap( mWorld );
  406.     //::LockPixels( mBM );
  407.     mBytesPerRow    = (**mBM).rowBytes & 0xFFF;
  408.     mBytesPerPix    = (**mBM).pixelSize / 8;
  409.     
  410.     #if GFORCE
  411.     // WARNING: Hack/Experimental code only!!!
  412.     CTabHandle ctab = ::GetCTable( 555 );
  413.     ColorSpec *specs;
  414.     long i;
  415.     specs = (**ctab).ctTable;
  416.     for ( i = 0; i < 256; i++ ) {
  417.         float v = ( (float) i ) / 255.0;
  418.         v = pow( v, 1.2 );
  419.         specs[ i ].rgb.red = v * 65535;
  420.         specs[ i ].rgb.green = v * 35535;
  421.         specs[ i ].rgb.blue = v * 35535;
  422.         specs[ i ].value = i;
  423.     }
  424.     (**ctab).ctSeed = GetCTSeed();
  425.     (**mBM).pmTable = ctab;
  426.     
  427.     // Restore current drawing environment
  428.     ::SetGWorld( (GWorldPtr)(savePort), saveDev );    
  429.     #endif
  430.  
  431.     #elif EG_WIN    
  432.  
  433.     // Initialize a bmap info struct
  434.     mInfo.bmiHeader.biSize            = sizeof( BITMAPINFOHEADER );
  435.     mInfo.bmiHeader.biWidth            = mX + 4;
  436.     mInfo.bmiHeader.biHeight        = mY + 2;
  437.     mInfo.bmiHeader.biPlanes        = 1;
  438.     mInfo.bmiHeader.biBitCount        = inDepth;
  439.     mInfo.bmiHeader.biCompression    = BI_RGB;
  440.     mInfo.bmiHeader.biSizeImage        = 0;
  441.     mInfo.bmiHeader.biXPelsPerMeter    = 0;
  442.     mInfo.bmiHeader.biYPelsPerMeter = 0;
  443.     mInfo.bmiHeader.biClrUsed        = 0;
  444.     mInfo.bmiHeader.biClrImportant    = 0;
  445.  
  446.  
  447.     // Tell windows to make a bitmap and give us acess to its pixel data
  448.     mBM = ::CreateDIBSection( mWorld, &mInfo, DIB_RGB_COLORS, &mBits, NULL, 0 );
  449.     HGDIOBJ oldBM = ::SelectObject( mWorld, mBM );
  450.     if ( oldBM ) 
  451.         ::DeleteObject( oldBM );    
  452.     
  453.     BITMAP b;
  454.     ::GetObject( mBM, sizeof( BITMAP ), &b );
  455.     mBytesPerRow    = b.bmWidthBytes;
  456.     mBytesPerPix    = b.bmBitsPixel / 8;
  457.  
  458. /*
  459.  
  460.     mInfo.bmiHeader.biSize            = sizeof( BITMAPINFOHEADER );
  461.     mInfo.bmiHeader.biWidth            = mX;
  462.     mInfo.bmiHeader.biHeight        = mY;
  463.     mInfo.bmiHeader.biPlanes        = 1;
  464.     mInfo.bmiHeader.biBitCount        = inDepth;
  465.     mInfo.bmiHeader.biCompression    = BI_RGB;
  466.     mInfo.bmiHeader.biSizeImage        = 0;
  467.     mInfo.bmiHeader.biXPelsPerMeter    = 39 * 96;
  468.     mInfo.bmiHeader.biYPelsPerMeter = 39 * 96;
  469.     mInfo.bmiHeader.biClrUsed        = 0;
  470.     mInfo.bmiHeader.biClrImportant    = 0;
  471.     *((long*) &mInfo.bmiColors) = 0;
  472.     
  473.     mBytesPerPix    = inDepth / 8;
  474.     mBytesPerRow    = mBytesPerPix * mX;
  475.  
  476.     mBuf.Dim( (mY+3) * mBytesPerRow );
  477.     mBits = mBuf.getCStr();
  478.     */
  479.     
  480.     #endif
  481. }
  482.  
  483.  
  484. void PixPort::Deactivate() {
  485.     
  486.     if ( ! IsFullscreen() ) 
  487.         return;
  488.         
  489.     #if EG_MAC && USE_DRAW_SPROCKETS
  490.     //GDHandle        saveDev;
  491.      //GrafPtr            savePort;
  492.     //::GetGWorld( (GWorldPtr*)(&savePort), &saveDev );
  493.     ::DSpContext_FadeGamma( mContextRef, 0, NULL );
  494.     ::DSpContext_SetState( mContextRef, kDSpContextState_Inactive );
  495.     ::DSpContext_Release( mContextRef );
  496.     ::DSpContext_FadeGamma( mContextRef, 100, NULL );    
  497.     ::InitCursor();
  498.     //::SetGWorld( (GWorldPtr)(savePort), saveDev );            
  499.     #endif
  500.     
  501.     #if USE_DIRECTX
  502.     EndFrame();
  503.     mContextRef -> Release();
  504.     mDDObj -> Release();
  505.     mDDObj = NULL;
  506.     ::ReleaseCapture();
  507.     while ( ::ShowCursor( true ) < 0 ) { }
  508.     #endif
  509.     
  510.     mContextRef = NULL;
  511. }
  512.  
  513.  
  514.  
  515.  
  516.  
  517. #define __clipPt( x, y )    \
  518.     if ( x < 0 )            \
  519.         x = 0;                \
  520.     else if ( x > mX )        \
  521.         x = mX;                \
  522.     if ( y < 0 )            \
  523.         y = 0;                \
  524.     else if ( y > mY )        \
  525.         y = mY;                \
  526.  
  527.  
  528.  
  529. #define __clipRect( inRect )            \
  530.     Rect r = inRect;                    \
  531.     __clipPt( r.left, r.top )            \
  532.     __clipPt( r.right, r.bottom )        \
  533.     long width     = r.right - r.left;        \
  534.     long height = r.bottom - r.top;
  535.  
  536.  
  537.  
  538.  
  539.  
  540.  
  541.  
  542. void PixPort::BeginFrame() {
  543.  
  544.     #if EG_MAC
  545.     
  546.     if ( IsFullscreen() ) {
  547.     
  548.         #if USE_DRAW_SPROCKETS
  549.         CGrafPtr thePort;
  550.         OSErr err;
  551.         err = ::DSpContext_GetBackBuffer( mContextRef, kDSpBufferKind_Normal, &thePort );
  552.         if ( thePort && ! err ) {
  553.             ::SetPort( (GrafPtr) thePort );
  554.             mBM = thePort -> portPixMap; }
  555.         else {
  556.             mBM = NULL;
  557.             Deactivate();
  558.         }
  559.         #endif
  560.         }
  561.     else if ( mWorld )
  562.         mBM    = ::GetGWorldPixMap( mWorld );
  563.         
  564.     if ( mBM )
  565.         mBits = ::GetPixBaseAddr( mBM );
  566.     #endif
  567.     
  568.     /*
  569.     #if USE_DIRECTX
  570.     if ( IsFullscreen() ) {
  571.         if ( ! mContextRef -> GetDC( &mFS_DC ) != DD_OK )
  572.             mFS_DC = NULL;
  573.     }
  574.     #endif*/
  575. }
  576.  
  577.  
  578. void PixPort::EndFrame() {
  579.  
  580.  
  581.     if ( IsFullscreen() ) {
  582.  
  583.         #if USE_DRAW_SPROCKETS
  584.         ::DSpContext_SwapBuffers( mContextRef, NULL, 0 );
  585.         #endif
  586.         
  587.         #if USE_DIRECTX && 0 
  588.         if ( mFS_DC ) {
  589.             mContextRef -> ReleaseDC( mFS_DC );
  590.             mFS_DC = NULL;
  591.         }
  592.         #endif
  593.     }
  594. }
  595.  
  596.  
  597.  
  598.  
  599.  
  600. long PixPort::GetPortColor( long inR, long inG, long inB ) {
  601.     int bitDepth  =mBytesPerPix << 3;
  602.     
  603.     long c;
  604.     
  605.     if ( inR > 0xFFFF )    inR = 0xFFFF;
  606.     if ( inG > 0xFFFF )    inG = 0xFFFF;
  607.     if ( inB > 0xFFFF )    inB = 0xFFFF;
  608.     if ( inR < 0 )        inR = 0;
  609.     if ( inG < 0 )        inG = 0;
  610.     if ( inB < 0 )        inB = 0;
  611.     
  612.     if ( bitDepth == 32 ) 
  613.         c = __Clr32( inR, inG, inB );
  614.     else if ( bitDepth == 16 )
  615.         c = __Clr16( inR, inG, inB );
  616.     else
  617.         c = __Clr8( inR, inG, inB );
  618.  
  619.     return c;
  620. }
  621.  
  622.  
  623.  
  624.  
  625.  
  626. long PixPort::SetBackColor( const RGBColor& RGB ) {
  627.  
  628.     mBackColor = GetPortColor( RGB );
  629.     
  630.     return mBackColor;
  631. }
  632.  
  633.  
  634. long PixPort::SetBackColor( long inR, long inG, long inB ) {
  635.     mBackColor = GetPortColor( inR, inG, inB );
  636.  
  637.     return mBackColor;
  638. }
  639.  
  640.  
  641. void PixPort::GaussBlur( int inBoxWidth, const Rect& inRect, void* inDestBits ) {    
  642.     
  643.     // Don't let us draw in random parts of memory -- clip inRect
  644.     __clipRect( inRect )
  645.     
  646.     
  647.     if ( inBoxWidth <= 1 )
  648.         return;
  649.     
  650.     // In Win32, everything's upside down
  651.     #if EG_WIN
  652.     r.top = mY - r.bottom;
  653.     #endif
  654.  
  655.     // 3 box convolutions, 3 colors per pixel, 4 bytes per color
  656.     long     boxTempSize    = 36 * inBoxWidth;
  657.     char*    tempBits    = NULL;
  658.     unsigned long*    boxTemp;
  659.     long    imgOffset    = mBytesPerPix * r.left + r.top * mBytesPerRow;
  660.     long    bytesNeeded    = mBytesPerRow * (mY + 2) + boxTempSize;
  661.     
  662.     #if EG_MAC
  663.     if ( mHndlSize < bytesNeeded ) {
  664.         OSErr err;
  665.         if ( mTempHndl ) {
  666.             ::TempDisposeHandle( mTempHndl, &err );
  667.             mHndlSize = 0;
  668.         }
  669.         
  670.         mTempHndl = ::TempNewHandle( bytesNeeded, &err );
  671.         if ( ! err ) {
  672.             tempBits = *mTempHndl;
  673.             mHndlSize = bytesNeeded;
  674.         }
  675.     }
  676.     #endif
  677.     
  678.     // Resort to app's heap for temp mem if failed temp mem attempt or in win32
  679.     if ( ! tempBits ) {
  680.         mTempBuf.Dim( bytesNeeded );
  681.         tempBits = mTempBuf.getCStr();
  682.     }
  683.  
  684.     // Have the box temp and the pixel temp rgns use the same handle
  685.     boxTemp = (unsigned long*) tempBits;
  686.     tempBits += boxTempSize;
  687.     
  688.     if ( ! inDestBits )
  689.         inDestBits = mBits;
  690.         
  691.     // Do a box blur on the x axis, transposing the source rgn to the dest rgn
  692.     // Then o a box blur on the transposed image, effectively blurring the y cords, transposing it to the dest
  693.     if ( mBytesPerPix == 2 )  {    
  694.         BoxBlur16( ( mBits + imgOffset), tempBits, inBoxWidth, width, height, mBytesPerRow, mBytesPerPix*height, boxTemp, mBackColor );
  695.         BoxBlur16( tempBits, ((char*) inDestBits + imgOffset), inBoxWidth, height, width, mBytesPerPix*height, mBytesPerRow, boxTemp, mBackColor );  }
  696.     else if ( mBytesPerPix == 4 ) {
  697.         BoxBlur32( ( mBits + imgOffset), tempBits, inBoxWidth, width, height, mBytesPerRow, mBytesPerPix*height, boxTemp, mBackColor );
  698.         BoxBlur32( tempBits, ((char*) inDestBits + imgOffset), inBoxWidth, height, width, mBytesPerPix*height, mBytesPerRow, boxTemp, mBackColor ); 
  699.     }
  700. }
  701.  
  702.  
  703.  
  704. void PixPort::CrossBlur( const Rect& inRect ) {    
  705.     
  706.     // Don't let us draw in random parts of memory -- clip inRect
  707.     __clipRect( inRect )
  708.     
  709.     
  710.     // In Win32, everything's upside down
  711.     #if EG_WIN
  712.     r.top = mY - r.bottom;
  713.     #endif
  714.  
  715.     // 3 box convolutions, 3 colors per pixel, 4 bytes per color
  716.     long    imgOffset    = mBytesPerPix * r.left + r.top * mBytesPerRow;
  717.     
  718.     mTempBuf.Dim( mX * 3 );
  719.     unsigned char* tempBits = (unsigned char*) mTempBuf.getCStr();
  720.  
  721.         
  722.     if ( mBytesPerPix == 2 ) 
  723.         CrossBlur16( ( mBits + imgOffset), width, height, mBytesPerRow, tempBits ); 
  724.     else if ( mBytesPerPix == 4 )
  725.         CrossBlur32( ( mBits + imgOffset), width, height, mBytesPerRow, tempBits );
  726.     
  727. }
  728.  
  729.  
  730.  
  731.  
  732.  
  733.  
  734. void PixPort::CopyBits( WindowPtr inDest, const Rect* inSrce, const Rect* inDestRect ) {
  735.     
  736.     #if EG_MAC
  737.     ::CopyBits( (BitMap*) *mBM, &inDest->portBits, inSrce, inDestRect, srcCopy, NULL );
  738.     #elif EG_WIN
  739.     HDC hdc = ::GetDC( inDest );
  740.     ::BitBlt( hdc, inDestRect -> left, inDestRect -> top, inDestRect -> right - inDestRect -> left, inDestRect -> bottom - inDestRect -> top, mWorld, inSrce -> left, inSrce -> top, SRCCOPY );
  741.     ::ReleaseDC( inDest, hdc );
  742.     #endif
  743. }
  744.  
  745.  
  746.  
  747.  
  748.  
  749. void PixPort::Line( int sx, int sy, int ex, int ey, long inColor ) {
  750.     
  751.     if ( mBytesPerPix == 2 ) 
  752.         Line16( sx, sy, ex, ey, inColor );
  753.     else if ( mBytesPerPix == 1 )
  754.         Line8 ( sx, sy, ex, ey, inColor );
  755.     else if ( mBytesPerPix == 4 ) 
  756.         Line32( sx, sy, ex, ey, inColor );
  757. }
  758.  
  759.  
  760.  
  761.  
  762. void PixPort::Line( int sx, int sy, int ex, int ey, const RGBColor& inS, const RGBColor& inE ) {
  763.     long R, G, B, dR, dG, dB, absdR, absdG, absdB;
  764.     
  765.     R = inS.red;
  766.     G = inS.green;
  767.     B = inS.blue;
  768.     dR = inE.red - R;
  769.     dG = inE.green - G;
  770.     dB = inE.blue - B;
  771.     absdR = dR & 0x7FFFFFFF;        // Abs value
  772.     absdG = dG & 0x7FFFFFFF;
  773.     absdB = dB & 0x7FFFFFFF;
  774.     
  775.     // If the endpoints have the same color, run the faster line procs (that just use one color)
  776.     if ( absdR < 520 && absdG < 520 && absdB < 520 ) {
  777.         long color;
  778.  
  779.         if ( mBytesPerPix == 2 ) {
  780.             color = __Clr16( R, G, B );
  781.             Line16( sx, sy, ex, ey, color ); }
  782.         else if ( mBytesPerPix == 4 ) {
  783.             color = __Clr32( R, G, B );
  784.             Line32( sx, sy, ex, ey, color ); }
  785.         else if ( mBytesPerPix == 1 ) {
  786.             color = __Clr8( R, G, B );
  787.             Line8 ( sx, sy, ex, ey, color );
  788.         } }
  789.     else {
  790.         if ( mBytesPerPix == 2 ) 
  791.             Line16( sx, sy, ex, ey, inS, dR, dG, dB );
  792.         else if ( mBytesPerPix == 4 ) 
  793.             Line32( sx, sy, ex, ey, inS, dR, dG, dB );
  794.         else if ( mBytesPerPix == 1 )
  795.             Line8 ( sx, sy, ex, ey, inS, dR, dG, dB );
  796.     }
  797. }
  798.  
  799.  
  800.  
  801. void PixPort::SetLineWidth( long inLineWidth ) {
  802.     if ( inLineWidth <= 0 )
  803.         mLineWidth = 1;
  804.     else if ( inLineWidth > MAX_LINE_WIDTH )
  805.         mLineWidth = MAX_LINE_WIDTH;
  806.     else
  807.         mLineWidth = inLineWidth;
  808. }
  809.  
  810. void PixPort::EraseRect( const Rect* inRect ) {
  811.     
  812.     if ( mBytesPerPix == 2 )
  813.         EraseRect16( inRect );
  814.     else if ( mBytesPerPix == 1 )
  815.         EraseRect8 ( inRect );
  816.     else if ( mBytesPerPix == 4 )
  817.         EraseRect32( inRect );
  818. }
  819.  
  820.  
  821.  
  822.  
  823. #define P_SZ    1
  824. #include "DrawXX.cpp"
  825.  
  826.  
  827. #undef P_SZ
  828. #define P_SZ    2
  829. #include "DrawXX.cpp"
  830.  
  831.  
  832. #undef P_SZ
  833. #define P_SZ    4
  834. #include "DrawXX.cpp"
  835.  
  836. /*
  837. #define HALFCORD    0x007F  /* 16 bits per cord, 8 bits for fixed decimal -> means +/- 127
  838.  
  839.  
  840. #define __loadGrad    g = *((unsigned long*) inGrad);                                            \
  841.                     xsrc = g >> 24;                                                            \
  842.                     ysrc = (g >> 8) & 0xFF;    
  843.  
  844. #define __calcP        v = g & 0xFF;            /* x - xsrc                                     \
  845.                     u = (g >> 16) & 0xFF;    /* y - ysrc                                     \
  846.                     u1 = 0x100 - u;            /* 1 - u                                         \
  847.                     p  = v * ( P3 * u1 + P4 * u ) + ( 0x100 - v ) * ( P1 * u1 + P2 * u );    
  848.  
  849.  
  850. #define __loadPX    P1     = *((unsigned short*) srceMap);                                        \
  851.                     P2  = P1 & 0xFF;                                                        \
  852.                     P1  = P1 >> 8;                                                            \
  853.                     P3    = *((unsigned short*) (srceMap + mBytesPerRow));                    \
  854.                     P4  = P3 & 0xFF;                                                        \
  855.                     P3  = P3 >> 8;                                                            \
  856. /*
  857. void PixPort::Fade( PixPort& ioDest, void* inGrad ) {
  858.     unsigned long g, p, x, y, xsrc, ysrc, u, v, u1, P1, P2, P3, P4, finalP;    
  859.     char* dest, *srceBase, *srceMap, *prevMap;
  860.     long destRowBytes = ioDest.mBytesPerRow;
  861.  
  862.     if ( mBytesPerPix != 1 )
  863.         return;
  864.         
  865.     long blah;
  866.     long* bptr = &blah;
  867.     
  868.     // For every pixel in the destination, find it's source via the gradient
  869.     for ( y = 0; y < mY; y++ ) {
  870.     
  871.         // Setup the dest row base address
  872.         dest = ioDest.mBits + destRowBytes * y;
  873.         
  874.         // Setup the source row base address, also offset to allow for negative grad components
  875.         srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD;
  876.         
  877.         for ( x = 0; x < mX; x += 4 ) {
  878.             // Extract the gradient information
  879.             __loadGrad
  880.             
  881.             // P1 - P2
  882.             // |     |
  883.             // P3 - P4
  884.             srceMap = srceBase + xsrc + ysrc * mBytesPerRow;
  885.             __loadPX
  886.     
  887.             __calcP
  888.             finalP = (p & 0xFFFF0000) << 8;
  889.             
  890.             
  891.             // **** x + 1
  892.             prevMap = srceMap;
  893.             __loadGrad
  894.             srceMap = srceBase + xsrc + ysrc * mBytesPerRow + 1;
  895.  
  896.             // If we don't already have the four fence pixels, load them from RAM
  897.             if ( srceMap != prevMap ) {
  898.                 __loadPX
  899.             }
  900.             __calcP
  901.             finalP |= (p & 0x00FF0000);
  902.             
  903.             // **** x + 2
  904.             prevMap = srceMap;
  905.             __loadGrad
  906.             srceMap = srceBase + xsrc + ysrc * mBytesPerRow + 2;
  907.  
  908.             // If we don't already have the four fence pixels, load them from RAM
  909.             if ( srceMap != prevMap ) {
  910.                 __loadPX
  911.             }
  912.             __calcP
  913.             finalP |= (p & 0xFFFF0000) >> 8;
  914.  
  915.  
  916.             // **** x + 3
  917.             prevMap = srceMap;
  918.             __loadGrad
  919.             srceMap = srceBase + xsrc + ysrc * mBytesPerRow + 3;
  920.  
  921.             // If we don't already have the four fence pixels, load them from RAM
  922.             if ( srceMap != prevMap ) {
  923.                 __loadPX
  924.             }
  925.             __calcP
  926.             finalP |= p >> 16;
  927.             *((unsigned long*) dest) = finalP; 
  928.  
  929.         
  930.             // Move to x+4
  931.             inGrad = ((long*) inGrad) + 4;
  932.             srceBase += 4;
  933.             dest += 4;
  934.         }
  935.     }
  936. }
  937. */
  938.  
  939.  
  940. #define HALFCORD    0x001F  /* 12 bits per cord, 5 bits for fixed decimal -> means +/- 127 */
  941.  
  942.  
  943. void PixPort::Fade( PixPort& ioDest, char* inGrad ) {
  944.     unsigned long p, x, y, u, v, u1, v1, P1, P2, P3, P4, bytesPerRow, codedDel, xGrad, yGrad;
  945.     char* dest, *srceBase, *srceMap, *prevLoc = 0;
  946.     long destRowBytes = ioDest.mBytesPerRow;
  947.  
  948.     if ( mBytesPerPix != 1 )
  949.         return;
  950.             
  951.     bytesPerRow = mBytesPerRow;
  952.     
  953.     // For every pixel in the destination, find it's source via the gradient
  954.     for ( y = 0; y < mY; y++ ) {
  955.     
  956.         // Setup the dest row base address
  957.         dest = ioDest.mBits + destRowBytes * y;
  958.         
  959.         // Setup the source row base address, also offset to allow for negative grad components
  960.         srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD;
  961.         
  962.         
  963.         for ( x = 0; x < mX; x++ ) {
  964.             // Extract the gradient information
  965.             // Format of a grad short:  ( ( (ddx + 128) * 16 ) << 20 ) | ( (ddy + 128) * 16 ) << 8
  966.             codedDel = *((unsigned long*) inGrad);    
  967.             inGrad += 3;
  968.             xGrad = codedDel >> 20;
  969.             yGrad = 0xFFF & ( codedDel >> 8 );
  970.         
  971.             // Get the vector to the source pixel
  972.             srceMap = srceBase + ( xGrad >> 6 ) + ( yGrad >> 6 ) * bytesPerRow;
  973.  
  974.             u = ( yGrad & 0x3F );        // y - ysrc
  975.             v = ( xGrad & 0x3F );        // x - xsrc
  976.             srceBase++;
  977.             
  978.             // P1 - P2
  979.             // |     |
  980.             // P3 - P4
  981.             P1  = ( (unsigned char*) srceMap )[0];
  982.             P2  = ( (unsigned char*) srceMap )[1];
  983.  
  984.             u1     = 0x40 - u;
  985.             P1  *= u1;
  986.             P2  *= u1;
  987.  
  988.             P3  = ( (unsigned char*) srceMap )[ bytesPerRow ];  
  989.             P4  = ( (unsigned char*) srceMap )[ bytesPerRow + 1 ];
  990.  
  991.             v1     = 0x40 - v;
  992.             P3 *= u;
  993.             P4 *= u;
  994.     
  995.             // Bilinear interpolation to approximate the source pixel value
  996.             p  = v * ( P2 + P4 ) + v1 * ( P1 + P3 );
  997.  
  998.  
  999.             // Store the calculated/dest pixel (rounding the fraction part of the pix value)
  1000.             // We divide by 12 decimal places because p is units squared (6 places per decimal)
  1001.             *((unsigned char*) dest) = ( 15 * p ) >> 16;    dest++; // 5 more dec places cuz of the mult by 31
  1002.  
  1003.         }
  1004.     }
  1005. }
  1006.  
  1007. /*
  1008. void PixPort::Fade( PixPort& ioDest, char* inGrad ) {
  1009.     unsigned long p, x, y, u, v, u1, v1, P1, P2, P3, P4, bytesPerRow;
  1010.     char* dest, *srceBase, *srceMap, *prevLoc = 0;
  1011.     long destRowBytes = ioDest.mBytesPerRow, xGrad, yGrad;
  1012.  
  1013.     if ( mBytesPerPix != 1 )
  1014.         return;
  1015.             
  1016.     bytesPerRow = mBytesPerRow;
  1017.     
  1018.     // For every pixel in the destination, find it's source via the gradient
  1019.     for ( y = 0; y < mY; y++ ) {
  1020.     
  1021.         // Setup the dest row base address
  1022.         dest = ioDest.mBits + destRowBytes * y;
  1023.         
  1024.         // Setup the source row base address, also offset to allow for negative grad components
  1025.         srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD;
  1026.         
  1027.         
  1028.         for ( x = 0; x < mX; x++ ) {
  1029.             // Extract the gradient information
  1030.             // Format of a grad short:  ( ( (ddx + 128) * 16 ) << 20 ) | ( (ddy + 128) * 16 ) << 8
  1031.             xGrad = *( (char*) inGrad );    inGrad++;
  1032.             yGrad = *( (char*) inGrad );    inGrad++;
  1033.         
  1034.             // Get the vector to the source pixel
  1035.             srceMap = srceBase + ( xGrad >> 2 ) + ( yGrad >> 2 ) * bytesPerRow;
  1036.  
  1037.             u = ( yGrad & 0x3 );        // y - ysrc
  1038.             v = ( xGrad & 0x3 );        // x - xsrc
  1039.             srceBase++;
  1040.             
  1041.             // P1 - P2
  1042.             // |     |
  1043.             // P3 - P4
  1044.             P1  = ( (unsigned char*) srceMap )[0];
  1045.             P2  = ( (unsigned char*) srceMap )[1];
  1046.  
  1047.             u1     = 0x4 - u;
  1048.             P1  *= u1;
  1049.             P2  *= u1;
  1050.  
  1051.             P3  = ( (unsigned char*) srceMap )[ bytesPerRow ];  
  1052.             P4  = ( (unsigned char*) srceMap )[ bytesPerRow + 1 ];
  1053.  
  1054.             v1     = 0x4 - v;
  1055.             P3 *= u;
  1056.             P4 *= u;
  1057.     
  1058.             // Bilinear interpolation to approximate the source pixel value
  1059.             p  = v * ( P2 + P4 ) + v1 * ( P1 + P3 );
  1060.  
  1061.  
  1062.             // Store the calculated/dest pixel (rounding the fraction part of the pix value)
  1063.             // We divide by 4 decimal places because p is units squared
  1064.             *((unsigned char*) dest) = ( 31 * p ) >> 9;    dest++; // 5 more dec places cuz of the mult by 31
  1065.  
  1066.         }
  1067.     }
  1068. }*/
  1069. /*
  1070. void PixPort::Fade( PixPort& ioDest, char* inGrad ) {
  1071.     unsigned long gDelta, p, x, y, u, v, u1, v1, P1, P2, P3, P4;
  1072.     char* dest, *srceBase, *srceMap, *prevLoc = 0;
  1073.     long destRowBytes = ioDest.mBytesPerRow, xGrad, yGrad;
  1074.  
  1075.     if ( mBytesPerPix != 1 )
  1076.         return;
  1077.             
  1078.     // For every pixel in the destination, find it's source via the gradient
  1079.     for ( y = 0; y < mY; y++ ) {
  1080.     
  1081.         // Setup the dest row base address
  1082.         dest = ioDest.mBits + destRowBytes * y;
  1083.         
  1084.         // Setup the source row base address, also offset to allow for negative grad components
  1085.         srceBase = mBits + y * mBytesPerRow;
  1086.         
  1087.         
  1088.         for ( x = 0; x < mX; x++ ) {
  1089.             // Extract the gradient information
  1090.             // Format of a grad short:  ( ( (ddx + 128) * 16 ) << 20 ) | ( (ddy + 128) * 16 ) << 8
  1091.             gDelta = *((long*) inGrad);    
  1092.             inGrad += 3;
  1093.             xGrad = ( (long) ( gDelta >> 20 ) ) - 0x7FF;
  1094.             yGrad = ( (long) ( ( gDelta >> 8 ) & 0xFFF ) ) - 0x7FF;
  1095.         
  1096.             // Get the vector to the source pixel
  1097.             srceMap = srceBase + ( xGrad >> 2 ) + ( yGrad >> 2 ) * mBytesPerRow;
  1098.  
  1099.             u = yGrad & 0x3;        // y - ysrc
  1100.             v = xGrad & 0x3;        // x - xsrc
  1101.             srceBase++;
  1102.             
  1103.             // P1 - P2
  1104.             // |     |
  1105.             // P3 - P4
  1106.             P1     = *((unsigned short*) srceMap);
  1107.             P3    = *((unsigned short*) (srceMap + mBytesPerRow));
  1108.  
  1109.             u1 = 0x4 - u;
  1110.             P2  = ( P1 & 0xFF ) * u1;
  1111.             P1  = ( P1 >> 8 ) * u1;
  1112.  
  1113.             v1     = 0x4 - v;
  1114.             P4  = ( P3 & 0xFF ) * u;
  1115.             P3  = ( P3 >> 8 ) * u;
  1116.     
  1117.             // Bilinear interpolation to approximate the source pixel value
  1118.             p  = v * ( P2 + P4 ) + v1 * ( P1 + P3 );
  1119.  
  1120.             // Store the calculated/dest pixel (rounding the fraction part of the pix value)
  1121.             // We divide by 10 decimal places because p is units squared
  1122.             *((unsigned char*) dest) = p >> 4;
  1123.         
  1124.             // Move to x+1
  1125.             dest++;
  1126.         }
  1127.     }
  1128. }
  1129. */
  1130.  
  1131.  
  1132. /*
  1133. void PixPort::Fade( PixPort& ioDest, char* inGrad ) {
  1134.     unsigned long gDelta, xGrad, yGrad, p, x, y, u, v, u1, P1, P2, P3, P4;
  1135.     char* dest, *srceBase, *srceMap, *prevLoc = 0;
  1136.     long destRowBytes = ioDest.mBytesPerRow;
  1137.  
  1138.     if ( mBytesPerPix != 1 )
  1139.         return;
  1140.             
  1141.     // For every pixel in the destination, find it's source via the gradient
  1142.     for ( y = 0; y < mY; y++ ) {
  1143.     
  1144.         // Setup the dest row base address
  1145.         dest = ioDest.mBits + destRowBytes * y;
  1146.         
  1147.         // Setup the source row base address, also offset to allow for negative grad components
  1148.         srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD;
  1149.         
  1150.         
  1151.         for ( x = 0; x < mX; x++ ) {
  1152.             // Extract the gradient information
  1153.             // Format of a grad short:  ( ( (ddx + 128) * 16 ) << 20 ) | ( (ddy + 128) * 16 ) << 8
  1154.             gDelta = *((long*) inGrad);    
  1155.             inGrad += 3;
  1156.             xGrad = ( gDelta >> 20 );
  1157.             yGrad = ( ( gDelta >> 8 ) & 0xFFF );
  1158.             
  1159.             // Get the vector to the source pixel
  1160.             srceMap = srceBase + ( xGrad >> 5 ) + ( yGrad >> 5 ) * mBytesPerRow;
  1161.             
  1162.             // P1 - P2
  1163.             // |     |
  1164.             // P3 - P4
  1165.             P1     = *((unsigned short*) srceMap);
  1166.             P2  = P1 & 0xFF;
  1167.             P1  = P1 >> 8;
  1168.             P3    = *((unsigned short*) (srceMap + mBytesPerRow));
  1169.             P4  = P3 & 0xFF;
  1170.             P3  = P3 >> 8;
  1171.     
  1172.             // Bilinear interpolation to approximate the source pixel value
  1173.             v = xGrad & 0x1F;        // x - xsrc
  1174.             u = yGrad & 0x1F;        // y - ysrc
  1175.             u1 = 0x20 - u;            // 1 - u
  1176.             p  = v * ( P2 * u1 + P4 * u ) + ( 0x1F - v ) * ( P1 * u1 + P3 * u );
  1177.  
  1178.             // Store the calculated/dest pixel (rounding the fraction part of the pix value)
  1179.             // We divide by 10 decimal places because p is units squared
  1180.             *((unsigned char*) dest) = p >> 10;
  1181.         
  1182.             // Move to x+1
  1183.             dest += 1;
  1184.             srceBase += 1;
  1185.         }
  1186.     }
  1187. }*/
  1188.  
  1189. /*
  1190.  
  1191.  
  1192. #define XSHIFT         10
  1193. #define HALFCORD    0x001F  /* 16 bits per cord, 8 bits for fixed decimal -> means +/- 127
  1194. #define CORDMASK    0x003F    /* 6 bits per cord
  1195. #define DECAYSHIFT    6        /* 4 bits left for the intensity decay factor 
  1196. #define DECAYMASK    0x000F
  1197.  
  1198.  
  1199. #define __fade( t, r, b)    t1 = (r >> 16) & 0xFF;        \
  1200.                             t2 = (r >> 8) & 0xFF;        \
  1201.                             pleft  = (t >> 24) + (b >> 24) + ((t >> 8) & 0xFF) + ((b >> 8) & 0xFF);            \
  1202.                             prght  = ((t >> 16) & 0xFF) + (t & 0xFF) + ((b >> 16) & 0xFF) + (b & 0xFF);        \
  1203.                             pleft  = 2 * (r >> 24) + 2 * ((r >> 8) & 0xFF);        \
  1204.                             prght  = 2 *((r >> 16) & 0xFF) + 2 * (r & 0xFF);        \
  1205.                             pleft    = ( pleft + 8 * t1 ) / 20;            \
  1206.                             prght    = ( prght + 8 * t2 ) / 20;
  1207.                     
  1208.  
  1209. void PixPort::Fade( PixPort& ioDest, short* inGrad ) {
  1210.     unsigned long g, t, b, r1, pleft, prght, x, y, xsrc, ysrc, t1, t2;    
  1211.     char* dest, *srceBase, *srceMap;
  1212.     long destRowBytes = ioDest.mBytesPerRow;
  1213.  
  1214.     if ( mBytesPerPix != 1 )
  1215.         return;
  1216.         
  1217.     long blah;
  1218.     long* bptr = &blah;
  1219.     
  1220.     // For every pixel in the destination, find it's source via the gradient
  1221.     for ( y = 0; y < mY; y += 1 ) {
  1222.     
  1223.         // Setup the dest row base address
  1224.         dest = ioDest.mBits + destRowBytes * y;
  1225.         
  1226.         // Setup the source row base address, also offset to allow for negative grad components
  1227.         srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD - 1;
  1228.         
  1229.         for ( x = 0; x < mX; x += 2 ) {
  1230.             // Extract the gradient information
  1231.             g = *((unsigned short*) inGrad);
  1232.             if ( y > 250 ) {
  1233.                 g = HALFCORD | (HALFCORD << XSHIFT);
  1234.             }
  1235.             xsrc = g >> XSHIFT;
  1236.             ysrc = g & CORDMASK;
  1237.             
  1238.             srceMap = srceBase + xsrc + ysrc * mBytesPerRow;
  1239.             t     = *((unsigned long*) (srceMap - mBytesPerRow));
  1240.             r1     = *((unsigned long*) srceMap);
  1241.             b    = *((unsigned long*) (srceMap + mBytesPerRow));
  1242.             
  1243.             __fade( t, r1, b )
  1244.             //pleft = t + b;
  1245.             //prght = r1;
  1246.             *((unsigned short*) dest) = (pleft << 8) | prght;
  1247.             //*((unsigned long*) bptr) = (pleft << 8) | prght;
  1248.  
  1249.         
  1250.             // Move to x+1
  1251.             inGrad++;
  1252.             dest += 2;
  1253.             srceBase += 2;
  1254.         }
  1255.     }
  1256. }
  1257. */
  1258.  
  1259.  
  1260. /*
  1261.  
  1262. #define __fade( t, r, b)    t1 = (r >> 16) & 0xFF;        \
  1263.                             t2 = (r >> 8) & 0xFF;        \
  1264.                             pleft    = ( ((t >> 8) & 0xFF) + ((b >> 8) & 0xFF) + (r >> 24) + 4 * t1 + t2 ) / 8;            \
  1265.                             prght    = ( (t & 0xFF) + (b & 0xFF) + t1 + 4 * t2 + (r & 0xFF) ) / 8;
  1266.                         
  1267.  
  1268. void PixPort::Fade( PixPort& ioDest, short* inGrad ) {
  1269.     unsigned long g, t, b, r1, pleft, prght, x, y, xsrc, ysrc, t1, t2;    
  1270.     char* dest, *srceBase, *srceMap;
  1271.     long destRowBytes = ioDest.mBytesPerRow;
  1272.  
  1273.     if ( mBytesPerPix != 1 )
  1274.         return;
  1275.         
  1276.     // For every pixel in the destination, find it's source via the gradient
  1277.     for ( y = 0; y < mY; y += 1 ) {
  1278.     
  1279.         // Setup the dest row base address
  1280.         dest = ioDest.mBits + destRowBytes * y;
  1281.         
  1282.         // Setup the source row base address, also offset to allow for negative grad components
  1283.         srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD - 1;
  1284.         
  1285.         for ( x = 0; x < mX; x += 2 ) {
  1286.             // Extract the gradient information
  1287.             g = *((unsigned short*) inGrad);
  1288.             if ( y > 250 ) {
  1289.                 g = HALFCORD | (HALFCORD << XSHIFT);
  1290.             }
  1291.             xsrc = g >> XSHIFT;
  1292.             ysrc = g & CORDMASK;
  1293.             
  1294.             srceMap = srceBase + xsrc + ysrc * mBytesPerRow;
  1295.             t     = *((unsigned short*) (srceMap - mBytesPerRow + 1));
  1296.             r1     = *((unsigned long*) srceMap);
  1297.             b    = *((unsigned short*) (srceMap + mBytesPerRow + 1));
  1298.             
  1299.             __fade( t, r1, b )
  1300.             *((unsigned short*) dest) = (pleft << 8) | prght;
  1301.         
  1302.             // Move to x+1
  1303.             inGrad++;
  1304.             dest += 2;
  1305.             srceBase += 2;
  1306.         }
  1307.     }
  1308. }
  1309. */
  1310.  
  1311.  
  1312. /*
  1313.  
  1314. #define __fade( r )        t1 = (r >> 16) & 0xFF;        \
  1315.                         t2 = (r >> 8) & 0xFF;        \
  1316.                         pleft    = ( (r >> 24) + 8 * t1 + t2 ) / 11;            \
  1317.                         prght    = ( t1 + 8 * t2 + (r & 0xFF) ) / 11;
  1318.  
  1319. void PixPort::Fade( PixPort& ioDest, short* inGrad ) {
  1320.     unsigned long g, r1, r2, pleft, prght, x, y, xsrc, ysrc, t1, t2;    
  1321.     char* dest, *srceBase, *srceMap;
  1322.     long destRowBytes = ioDest.mBytesPerRow;
  1323.  
  1324.     if ( mBytesPerPix != 1 )
  1325.         return;
  1326.         
  1327.     // For every pixel in the destination, find it's source via the gradient
  1328.     for ( y = 0; y < mY; y += 2 ) {
  1329.     
  1330.         // Setup the dest row base address
  1331.         dest = ioDest.mBits + destRowBytes * y;
  1332.         
  1333.         // Setup the source row base address, also offset to allow for negative grad components
  1334.         srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD - 1;
  1335.         
  1336.         for ( x = 0; x < mX; x += 2 ) {
  1337.             // Extract the gradient information
  1338.             g = *((unsigned short*) inGrad);
  1339.             if ( y > 250 ) {
  1340.                 g = HALFCORD | (HALFCORD << XSHIFT);
  1341.             }
  1342.             xsrc = g >> XSHIFT;
  1343.             ysrc = g & CORDMASK;
  1344.             
  1345.             srceMap = srceBase + xsrc + ysrc * mBytesPerRow;
  1346.             r1     = *((unsigned long*) srceMap);
  1347.             r2    = *((unsigned long*) (srceMap + mBytesPerRow));
  1348.             
  1349.             __fade( r1 )
  1350.             *((unsigned short*) dest) = (pleft << 8) | prght;
  1351.             
  1352.             __fade( r2 )
  1353.             *((unsigned short*) (dest + destRowBytes)) = (pleft << 8) | prght;
  1354.             
  1355.             // Move to x+1
  1356.             inGrad++;
  1357.             dest += 2;
  1358.             srceBase += 2;
  1359.         }
  1360.     }
  1361. }*/
  1362.  
  1363.  
  1364.  
  1365.  
  1366. // Random code segments that were tried/experimented with and tossed...
  1367.  
  1368. /*
  1369. int w, t, dx = ex - sx, dy = ey - sy, xDirection, yDirection, error_term;
  1370.     
  1371.         // Let a dot have a slope of 0
  1372.         if ( dx == 0 && dy == 0 )
  1373.             dx = 1;
  1374.             
  1375.         // Make sure we have a long enough path to step thru
  1376.         dx *= mLineWidth;
  1377.         dy *= mLineWidth;
  1378.         
  1379.         // Extend the line by w/2 at the endpoints
  1380.         movePt( sx, sy, -dx, -dy, mLineWidth / 2 );
  1381.         movePt( ex, ey, dx, dy, mLineWidth / 2 );
  1382.  
  1383.         // Offset the line w/2    
  1384.         movePt( sx, sy, dy, -dx, mLineWidth / 2 );
  1385.         movePt( ex, ey, dy, -dx, mLineWidth / 2 );
  1386.         
  1387.         int tx = sx, ty = sy;
  1388.         movePt( tx, ty, dx, dy, mLineWidth * dy / dx );
  1389.         for ( ; sy < tx; sy++ ) {
  1390.     
  1391.             if ( mBytesPerPix == 2 ) 
  1392.                 Line16( sx, sy, ex, ey, inColor, 0 );
  1393.             else if ( mBytesPerPix == 4 ) 
  1394.                 Line32( sx, sy, ex, ey, inColor, 0 );
  1395.             else if ( mBytesPerPix == 1 ) 
  1396.                 Line8 ( sx, sy, ex, ey, inColor, 0 );
  1397.         }*/
  1398.  
  1399.     /*
  1400.         int w, t, dx = ex - sx, dy = ey - sy, xDirection, yDirection, error_term;
  1401.     
  1402.         // Let a dot have a slope of 0
  1403.         if ( dx == 0 && dy == 0 )
  1404.             dx = 1;
  1405.             
  1406.         // Make sure we have a long enough path to step thru
  1407.         dx *= mLineWidth;
  1408.         dy *= mLineWidth;
  1409.         
  1410.         // Offset the line w/2    
  1411.         movePt( sx, sy, dy, -dx, mLineWidth / 2 );
  1412.         movePt( ex, ey, dy, -dx, mLineWidth / 2 );
  1413.         
  1414.         // Extend the line by w/2 at the endpoints
  1415.         movePt( sx, sy, -dx, -dy, mLineWidth / 2 );
  1416.         movePt( ex, ey, dx, dy, mLineWidth / 2 );
  1417.         
  1418.         t = dx; dx = -dy; dy = t;
  1419.         // moving left or right?
  1420.         if ( dx < 0 ) {
  1421.             xDirection = -1;
  1422.             dx = -dx; }
  1423.         else if ( dx > 0 ) 
  1424.             xDirection = 1;  
  1425.         else 
  1426.             xDirection = 0;
  1427.  
  1428.         // moving up or down?
  1429.         if ( dy < 0 ) {
  1430.             yDirection = -1;
  1431.             dy = -dy; }
  1432.         else if ( dy > 0 )
  1433.             yDirection = 1;  
  1434.         else
  1435.             yDirection = 0;
  1436.  
  1437.         error_term = 0;        
  1438.                 
  1439.         // Walf thru the width
  1440.         for ( w = 0; w < mLineWidth; w++ ) {        
  1441.  
  1442.             if ( dx >= dy ) {
  1443.                 sx += xDirection;
  1444.                 ex += xDirection;
  1445.  
  1446.                 // Check to see if we need to move the pixelOffset in the y direction.
  1447.                 error_term += dy;
  1448.                 if ( error_term > dx ) {
  1449.                     error_term -= dx;
  1450.                     sy += yDirection;
  1451.                     ey += yDirection;
  1452.                 } }
  1453.             else {                
  1454.                 sy += yDirection;
  1455.                 ey += yDirection;
  1456.                 
  1457.                 // Check to see if we need to move the pixelOffset in the y direction.
  1458.                 error_term += dx;
  1459.                 if ( error_term > dy ) {
  1460.                     error_term -= dy;
  1461.                     sx += xDirection;
  1462.                     ex += xDirection;
  1463.                 }
  1464.             }
  1465.     
  1466.             if ( mBytesPerPix == 2 ) 
  1467.                 Line16( sx, sy, ex, ey, inColor, 0 );
  1468.             else if ( mBytesPerPix == 4 ) 
  1469.                 Line32( sx, sy, ex, ey, inColor, 0 );
  1470.             else if ( mBytesPerPix == 1 ) 
  1471.                 Line8 ( sx, sy, ex, ey, inColor, 0 );
  1472.         }
  1473.     }*/
  1474.  
  1475.  
  1476.  
  1477.  
  1478.  
  1479.  
  1480. /*
  1481. void PixPort::LineW( int sx, int sy, int ex, int ey, long inColor ) {
  1482.     int i;
  1483.  
  1484.     int dx = ex - sx;
  1485.     int dy = ey - sy;
  1486.  
  1487.     // Let a dot have a slope of 0
  1488.     if ( dx == 0 && dy == 0 )
  1489.         dx = 1;
  1490.         
  1491.     // Make sure we have a long enough path to step thru
  1492.     dx *= mLineWidth;
  1493.     dy *= mLineWidth;
  1494.     
  1495.     // Extend the line by w/2 at the endpoints
  1496.     movePt( sx, sy, -dx, -dy, mLineWidth / 2 );
  1497.     movePt( ex, ey, dx, dy, mLineWidth / 2 );
  1498.  
  1499.     // Offset the line w/2    
  1500.     movePt( sx, sy, dy, -dx, mLineWidth / 2 );
  1501.     movePt( ex, ey, dy, -dx, mLineWidth / 2 );
  1502.  
  1503.     if ( dx < 0 )
  1504.         dx = -dx;
  1505.     if ( dy < 0 )
  1506.         dy = -dy;
  1507.     
  1508.     // For near horizontal slopes, draw multiple horizontal lines    
  1509.     if ( dy != 0 ) {
  1510.         if ( dx / dy > 5 )
  1511.             dy = 0;
  1512.     }
  1513.             
  1514.     if ( mLineWidth + 3 < dy ) {
  1515.         float fdy = ((float) dy) * ((float) dy);
  1516.         float fdx = ((float) dx) * ((float) dx);
  1517.         int w = ((float) mLineWidth) * sqrt( (1.0 + fdx / fdy) ) + 0.31;
  1518.         LineW16( sx, sy, ex, ey, w, inColor ); }
  1519.     else {
  1520.         sy -= mLineWidth / 2; ey -= mLineWidth / 2;
  1521.         for ( i = 0; i < mLineWidth; i++ ) {
  1522.             Line16( sx, sy, ex, ey, inColor );
  1523.             sy++;
  1524.             ey++;
  1525.         }
  1526.     }        
  1527.  
  1528.         // Find xleft
  1529.         // Set the scane width's worth of pixels from xlefr
  1530.     
  1531.     // Fill bottom triangle
  1532.  
  1533. }
  1534.  
  1535.  
  1536. void PixPort::movePt(  int& ioX, int& ioY, int dx, int dy, int inDist ) {
  1537.     int i, xDirection, yDirection, error_term;
  1538.             
  1539.     // moving left or right?
  1540.     if ( dx < 0 ) {
  1541.         xDirection = -1;
  1542.         dx = -dx; }
  1543.     else if ( dx > 0 ) 
  1544.         xDirection = 1;  
  1545.     else 
  1546.         xDirection = 0;
  1547.  
  1548.     // moving up or down?
  1549.     if ( dy < 0 ) {
  1550.         yDirection = -1;
  1551.         dy = -dy; }
  1552.     else if ( dy > 0 )
  1553.         yDirection = 1;  
  1554.     else
  1555.         yDirection = 0;
  1556.  
  1557.     error_term = 0;
  1558.  
  1559.     if ( dx >= dy ) {
  1560.         
  1561.         // Start counting off in x
  1562.         for ( i = 0; i < inDist; i++) {
  1563.         
  1564.             ioX += xDirection;
  1565.  
  1566.             // Check to see if we need to move the pixelOffset in the y direction.
  1567.             error_term += dy;
  1568.             if ( error_term >= dx ) {
  1569.                 error_term -= dx;
  1570.                 ioY += yDirection;
  1571.             }
  1572.         } }
  1573.     else {
  1574.         // Start counting off in y
  1575.         for ( i = 0; i <= inDist; i++) {
  1576.         
  1577.             ioY += yDirection;
  1578.             
  1579.             // Check to see if we need to move the pixelOffset in the y direction.
  1580.             error_term += dx;
  1581.             if ( error_term >= dy ) {
  1582.                 error_term -= dy;
  1583.                 ioX += xDirection;
  1584.             }
  1585.         }
  1586.     }
  1587. }
  1588.  
  1589.  
  1590. */
  1591.  
  1592.  
  1593.